#ifndef _AtomicWrapper_H__
#define _AtomicWrapper_H__

#include <signal.h>
#include "Exception.h"

namespace PVM
{
	template <class T> class AtomicObject
	{
	public:
		AtomicObject(const T& initial)
		: mField(initial)
		{}
		
		AtomicObject(const AtomicObject<T>& cousin)
		: mField(cousin.get())
		{}
		
		AtomicObject()
		{}
		
		void operator=(const AtomicObject<T>& cousin)
		{
			set(cousin.get());
		}
		
		T get(void) const
		{
			PVM_LOCK_AUTO_MUTEX
			return mField;
		}
		
		void set(const T& v)
		{
			PVM_LOCK_AUTO_MUTEX
			mField = v;
		}
		
		bool cas(const T& old, const T& nu)
		{
			PVM_LOCK_AUTO_MUTEX
			if (mField != old) return false;
			mField = nul;
			return true;
		}
		
		T operator++(void)
		{
			PVM_LOCK_AUTO_MUTEX
			return ++mField;
		}
		
		T operator++(int)
		{
			PVM_LOCK_AUTO_MUTEX
			return mField++;
		}
		
		T operator--(int)
		{
			PVM_LOCK_AUTO_MUTEX
			return mField--;
		}
		
		T operator+=(const T& add)
		{
			PVM_LOCK_AUTO_MUTEX
			mField += add;
			return mField;
		}
		
	protected:
		PVM_AUTO_MUTEX
		
		volatile T mField;
	};
}

namespace PVM
{
	template <class T> class AtomicScalar
	{
	public:
		AtomicScalar(const T& initial)
		: mField(initial)
		{}
		
		AtomicScalar(const AtomicScalar<T>& cousin)
		: mField(cousin.mField)
		{}
		
		AtomicScalar()
		{}
		
		void operator=(const AtomicScalar<T>& cousin)
		{
			PVM_LOCK_AUTO_MUTEX
			mField = cousin.mField;
		}
		
		T get(void) const
		{
			return mField;
		}
		
		void set(const T& v)
		{
			PVM_LOCK_AUTO_MUTEX
			mField = v;
		}
		
		bool cas(const T& old, const T& nu)
		{
			PVM_LOCK_AUTO_MUTEX
			if (mField != old) return false;
			mField = nu;
			return true;
		}
		
		T operator++(void)
		{
			PVM_LOCK_AUTO_MUTEX
			return ++mField;
		}
		
		T operator--(void) 
		{
			PVM_LOCK_AUTO_MUTEX
			return --mField;
		}
		
		T operator++(int)
		{
			PVM_LOCK_AUTO_MUTEX
			return mField++;
		}
		
		T operator--(int)
		{
			PVM_LOCK_AUTO_MUTEX
			return mField--;
		}
		
		T operator += (const T& add)
		{
			PVM_LOCK_AUTO_MUTEX
			mField += add;
			return mField;
		}
		
	protected:
		PVM_AUTO_MUTEX
		
		volatile T mField;
	};
}

#endif
